
#include "stdio.h"
#include "string.h"
#include "errno.h"
#include "stdlib.h"
#include "unistd.h"
#include "stdint.h"

#include "cJSON.h"

#define CJSON_MAX_SIZE  (1024 * 10)

static void usage(char *argv)
{
    fprintf(stderr, "Usage: %s [OPTIONS]\r\n\r\n"
                    "Options:\r\n"
                    " -i                        input json file.\r\n"
                    " -k                        key\r\n"
                    " -h                        help.\r\n\r\n",
                    argv
            );
}

cJSON *file2json(const char *filename)
{
    cJSON *root = NULL;
    uint8_t *buf = NULL;
    uint32_t len = 0;
    FILE *fp = NULL;
    int32_t rc = -1;

    if(NULL == filename) {
        return NULL;
    }
    fp = fopen(filename, "rb");
    if(fp == NULL){
        fprintf(stderr, "fopen %s failed, %s \r\n", filename, strerror(errno));
        return NULL;
    }
    fseek(fp, 0, SEEK_END);
    len = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    if(len > CJSON_MAX_SIZE) {
        fprintf(stderr, "too big file %s , size = %d\r\n", filename, len);
        fclose(fp);
        return NULL;
    }

    buf = (uint8_t *)malloc(len + 1);
    if(NULL == buf) {
        fprintf(stderr, "malloc(%d)\r\n failed", len);
        fclose(fp);
        return NULL;
    }
    memset(buf, 0, len + 1);
    rc = fread(buf, 1, len, fp);
    if(len != rc) {
        fprintf(stderr, "fread failed, %s\r\n", strerror(errno));
        fclose(fp);
        free(buf);
        return NULL;
    }
    fclose(fp);
    root = cJSON_Parse((char *)buf);
    free(buf);
    return root;
}

int main(int argc, char *argv[])
{
    int opt = 0;
    const char *file = NULL;
    const char *key = NULL;
    char *value = NULL;
    cJSON *root = NULL;

    while(1) {
        opt = getopt(argc, argv, "i:k:h");
        if (opt == -1) {
            break;
        }
        switch (opt) {
            case 'i':
                file = optarg;
                break;
            case 'k':
                key = optarg;
                break;
            case 'h':
                usage(argv[0]);
                return 0;
            case '?':
                usage(argv[0]);
                return -1;
        }
    }
    if(NULL == file || NULL == key) {
        usage(argv[0]);
        return -1;
    }
    root = file2json(file);
    if(NULL == root) {
        fprintf(stderr, "Invalid json file\r\n");
        return -1;
    }
    value = cJSON_GetObjectString(root, key);
    cJSON_Delete(root);
    if(NULL == value) {
        fprintf(stderr, "key %s not found\r\n", key);
        return -1;
    }
    fprintf(stdout, "%s\n", value);
    return 0;
}
